package com.vert.c3p0;


import com.mchange.v2.c3p0.ComboPooledDataSource;



import java.beans.PropertyVetoException;
import java.lang.reflect.Field;
import java.sql.Date;
import java.sql.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Classname C3P0DBSql
 * @Description TODO
 * @Date 2022/3/28 11:04
 * @Created by XiongXiong
 * @Author: X.I.O
 */
public class C3P0DBSql {



    private boolean flag = false;

    private String url;

    private String driver;

    private String password;

    private String username;

    private Connection connection;

    private static final ComboPooledDataSource ds = new ComboPooledDataSource();


    public C3P0DBSql(Map<String, String> stringMap) {
        this.url = stringMap.get("url");
        this.driver = stringMap.get("driver");
        this.password = stringMap.get("password");
        this.username = stringMap.get("username");
        this.flag = this.url != null && this.driver != null && this.username != null && this.password != null;
        this.initConnection();
    }

    public C3P0DBSql(String url, String driver, String username, String password) {
        this.url = url;
        this.driver = driver;
        this.username = username;
        this.password = password;
        this.flag = url != null && driver != null && username != null && password != null;
        this.initConnection();
    }

    public C3P0DBSql() throws Exception {
        throw new Exception("禁止这样使用");
    }



    public Map<String, Object> selectMapObjs(String sql) {
        Map<String, Object> objectMap = null;
        ResultSet resultSet = this.sqlExecuteQuery(sql);
        if (resultSet == null) {
            return objectMap;
        } else {
            String[] fields = this.getFeildList(resultSet);
            try {
                if (resultSet.next()) {
                    objectMap = new HashMap(1);
                    for(int i = 0; i < fields.length; ++i) {
                        String feildName = fields[i];
                        Object value = resultSet.getObject(feildName);
                        objectMap.put(feildName, value);
                    }
                    return objectMap;
                }
            } catch (Exception var11) {
                var11.printStackTrace();
            }
            return objectMap;
        }
    }

    public List<Map<String, Object>> selectMapObjList(String sql) {
        System.out.println(sql);
        ResultSet resultSet = this.sqlExecuteQuery(sql);
        List<Map<String, Object>> mapList = null;
        if (resultSet != null && this.flag) {
            String[] fields = this.getFeildList(resultSet);
            try {
                mapList = new ArrayList(50);
                while(resultSet.next()) {
                    Map<String, Object> stringObjectMap = new HashMap();
                    for(int i = 0; i < fields.length; ++i) {
                        String feildName = fields[i];
                        Object value = resultSet.getObject(feildName);

                        stringObjectMap.put(feildName, value);
                    }
                    mapList.add(stringObjectMap);
                }
            } catch (Exception var12) {
                var12.printStackTrace();
            }
            return mapList;
        } else {
            return mapList;
        }
    }

    public List<String> selectStringList(String sql){
        ResultSet resultSet = this.sqlExecuteQuery(sql);
        List<String> mapList = null;
        if (resultSet != null && this.flag) {
            String[] fields = this.getFeildList(resultSet);
            try {
                mapList = new ArrayList(50);
                while(resultSet.next()) {
                    String str=null;
                    for(int i = 0; i < fields.length; ++i) {
                        String feildName = fields[i];
                        Object value = resultSet.getObject(feildName);
                        if(value!=null){
                            str=String.valueOf(value);
                        }
                    }
                    if(str!=null){
                        mapList.add(str);
                    }
                }
            } catch (Exception var12) {
                var12.printStackTrace();
            }
            return mapList;
        } else {
            return mapList;
        }
    }



    public Boolean sqlListExecute(List<String> strings){
        if (strings==null){
            return false;
        }
        List<String> stringList=new ArrayList<>(1000);
        for (int i = 0; i < strings.size(); i++) {
            stringList.add(strings.get(i));
            if(i%1000==0){
                String excelSql=String.join(";",strings);
                this.sqlExecute(excelSql);
                stringList.clear();
            }
        }
        if(stringList.size()!=0){
            String excelSql = stringList.stream().collect(Collectors.joining(";"));
            this.sqlExecute(excelSql);
        }
        return true;
    }

    public <T> List<T> selectMapObjList(String sql,Class<T> cls) {
        ResultSet resultSet = this.sqlExecuteQuery(sql);
        List<T> mapList = null;
        if (resultSet != null && this.flag) {
            String[] fields = this.getFeildList(resultSet);
            Field[] tFields=cls.getDeclaredFields();
            try {
                mapList = new ArrayList(50);
                while(resultSet.next()) {
                    T t=cls.newInstance();
                    for(int i = 0; i < fields.length; ++i) {
                        String feildName = fields[i];
                        Field field=getFieldByName(feildName,tFields);
                        field.setAccessible(true);
                        Object value = resultSet.getObject(feildName);
                        field.set(t,value);
                    }
                    mapList.add(t);
                }
            } catch (Exception var12) {
                var12.printStackTrace();
            }finally {
               // closeConnection();
            }
            return mapList;
        } else {
            return mapList;
        }
    }


    /**
     * sql 格式 insert into table_name ('field_1','field_2') values ('?','?')
     *
     * List<Object> objects  [value1,value2]
     * @param sql
     * @param objects
     */
    public void insert(String sql,List<Object> objects){
        PreparedStatement sta=null;
        try{
            sta=this.connection.prepareStatement(sql);
            for (int i = 0; i < objects.size(); i++) {
                Object obj=objects.get(i);
                int num=i+1;
                insertDealObject(sta,num,obj);
            }
            int rows = sta.executeUpdate();
            if(rows > 0) {
                System.out.println("operate successfully!");
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
               // sta.close();
            }catch (Exception e){
                e.printStackTrace();
            }
            //closeConnection();
        }
    }


    private void insertDealObject(PreparedStatement sta,Integer num,Object obj) throws SQLException {
        if(obj instanceof String){
            sta.setString(num,(String) obj);
        }
        if(obj instanceof Integer){
            sta.setInt(num,(int)obj);
        }
        if(obj instanceof Double){
            sta.setDouble(num,(Double)obj);
        }
        if(obj instanceof  Float){
            sta.setFloat(num,(Float)obj);
        }
        if(obj instanceof Date){
            sta.setDate(num,(Date)obj);
        }
        if(obj instanceof Blob){
            sta.setBlob(num,(Blob)obj);
        }
    }






    public Field getFieldByName(String name,Field[] fields){
        for (int i = 0; i < fields.length; i++) {
            Field field=fields[i];
            if(!name.equals(field.getName())){
                continue;
            }
            return field;
        }
        return null;
    }

    public boolean updateSql(String sql){
        return sqlExecute(sql);
    }

    public boolean sqlExecute(String sql) {
        boolean flag = false;
        Statement stmt = null;
        try {
            stmt = this.connection.createStatement();
            flag = stmt.execute(sql);
            return flag;
        } catch (Exception var8) {
            var8.printStackTrace();
        }finally {
            //closeConnection();
        }
        return flag;
    }

    private String[] getFeildList(ResultSet rs) {
        try {
            ResultSetMetaData rsmd = rs.getMetaData();
            String[] lie = new String[rsmd.getColumnCount()];
            for(int i = 1; i < rsmd.getColumnCount() + 1; ++i) {
                lie[i - 1] = rsmd.getColumnName(i);
            }
            return lie;
        } catch (Exception var5) {
            var5.printStackTrace();
            return new String[0];
        }
    }

    private ResultSet sqlExecuteQuery(String sql) {
        Statement stmt = null;
        ResultSet rs = null;
        try {
            if (this.connection == null) {
                return null;
            } else {
                stmt = this.connection.createStatement();
                rs = stmt.executeQuery(sql);
                return rs;
            }
        } catch (Exception var5) {
            var5.printStackTrace();
            return rs;
        }
    }

    private void initConnection() {
        try {
            ds.setDriverClass(driver);
            ds.setJdbcUrl(url);
            ds.setUser(username);
            ds.setPassword(password);

            //当连接池中的连接耗尽的时候c3p0一次同时获取的连接数
            ds.setAcquireIncrement(3);
            //初始化数据库连接池时连接的数量
            ds.setInitialPoolSize(10);
            //数据库连接池中的最小的数据库连接数
            ds.setMinPoolSize(2);
            //数据库连接池中的最大的数据库连接数
            ds.setMaxPoolSize(10);
            connection = ds.getConnection();
        } catch (PropertyVetoException var3) {
            var3.printStackTrace();
        }catch (SQLException var4){
            var4.printStackTrace();
        }
    }


    private Map<String, String> stringMap(Map<String, String> stringMap) {
        Iterator var2 = stringMap.entrySet().iterator();
        while(var2.hasNext()) {
            Map.Entry<String, String> map = (Map.Entry)var2.next();
            String key = (String)map.getKey();
            stringMap.put(key.toLowerCase(), map.getValue());
            stringMap.remove(key, map.getValue());
        }
        return stringMap;
    }

    private void closeConnection() {
        try {
            if(connection!=null){
                connection.close();
            }
        } catch (SQLException var2) {
            var2.printStackTrace();
        }
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Connection getConnection() {
        return connection;
    }
}
